# -*- coding: utf-8 -*-
# @Author	: brotherbaby
# @Date		: 2023/11/2 9:37
# @Last Modified by:   brotherbaby
# @Last Modified time: 2023/11/2 9:37
# Thanks for your comments!

import json
import logging
import time
import traceback

from alibabacloud_dysmsapi20170525 import models as dysmsapi_20170525_models
from alibabacloud_dysmsapi20170525.client import Client as Dysmsapi20170525Client
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_tea_util import models as util_models
from alibabacloud_tea_util.client import Client as UtilClient
from flask import request

from src.config import CONF
from src.consts import SmsTemplateTake, ItemCategoryDescribeMap
from src.db_proxy.connect import DbConnector
from src.db_proxy.models.operation import Operation
from src.db_proxy.models.order import Order
from src.db_proxy.models.person import Person
from src.db_proxy.models.shoes_detail import ShoesDetail
from src.db_proxy.models.site import Site
from src.tornadoweb_app import app
from src.utils.singleton import singleton
from .utils import verify_token

logger = logging.getLogger(__name__)


@app.route("/wechat_milangze/send_sms_takeshoes", methods=["POST"])
def send_sms_takeshoes_api():
    resp = {"code": 0, "message": "success"}
    try:
        params = request.get_json()
        for f in ["client_type", "access_token"]:
            if not params.get(f):
                resp.update({"code": -1, "message": "lack %s" % f})
                return json.dumps(resp)
        if not verify_token(params.get("access_token"), params.get("client_type")):
            resp.update({"code": 403, "message": "invalid access_token, query new one and try again"})
            return json.dumps(resp)
        db_conn = DbConnector()
        session = db_conn.get_session()
        ali_sms = AliyunSMS()
        if params.get("phone") and params.get("name") and params.get("site_name"):
            ali_sms.send_sms(params["phone"],
                             {
                                 "name": params.get("name"),
                                 "type_name": ItemCategoryDescribeMap[params.get("item_category", 1) or 1],
                                 "site_name": params.get("site_name")
                             },
                             SmsTemplateTake.TemplateCode.value,
                             SmsTemplateTake.SignName.value)
        elif params.get("shoes_ecode"):
            if isinstance(params.get("shoes_ecode"), str):
                params["shoes_ecode"] = [params.get("shoes_ecode")]
            session.query(ShoesDetail).filter(ShoesDetail.shoes_ecode.in_(params["shoes_ecode"])).update({"status": 5})
            sds = session.query(ShoesDetail).filter(ShoesDetail.shoes_ecode.in_(params["shoes_ecode"])).all()
            for sd in sds:
                session.add(Operation(
                    order_id=sd.order_id,
                    shoes_ecode=sd.shoes_ecode,
                    operation_type=5,  # 完成
                    operation_time=int(time.time() * 1000),
                    operator=params.get("operator", "")
                ))
            order_ids = [item.order_id for item in sds]
            orders = session.query(Order, Person, Site).filter(Order.id.in_(order_ids)).join(Person).join(Site).all()
            per_info = {}
            per_shoes = {}  # {person_id: [{"item_category": order.item_category, "site_name": site.name}]}
            for ord in orders:
                order, per, site = ord
                if per.id not in per_info:
                    per_info[per.id] = per
                if per.id in per_shoes:
                    per_shoes[per.id].append({"item_category": order.item_category, "site_name": site.name})
                else:
                    per_shoes[per.id] = [{"item_category": order.item_category, "site_name": site.name}]
            for person_id, v in per_shoes.items():
                for item in v:
                    person_obj = per_info[person_id]
                    ali_sms.send_sms(person_obj.phone,
                                     {
                                         "name": person_obj.name,
                                         "type_name": ItemCategoryDescribeMap[item.get("item_category", 1) or 1],
                                         "site_name": item["site_name"]
                                     },
                                     SmsTemplateTake.TemplateCode.value,
                                     SmsTemplateTake.SignName.value)
        else:
            logger.error("invalid input.")
            resp.update({"code": -1, "message": "请检查入参"})
            return json.dumps(resp)
    except Exception as e:
        logger.error(traceback.format_exc())
        resp.update({"code": -1, "message": str(e)})
    finally:
        if "session" in locals() and "db_conn" in locals():
            session.commit()
            db_conn.close_session(session)
    return json.dumps(resp)


@singleton
class AliyunSMS:
    def __init__(self,
                 access_key_id=None,
                 access_key_secret=None,
                 ):
        """
        使用AK&SK初始化账号Client
        @param access_key_id:
        @param access_key_secret:
        @return: Client
        @throws Exception
        """
        if not (access_key_id and access_key_secret):
            access_key_id = CONF.app.get("alisms", {}).get("app_id")
            access_key_secret = CONF.app.get("alisms", {}).get("app_secret")
        config = open_api_models.Config(
            # 必填，您的 AccessKey ID,
            access_key_id=access_key_id,
            # 必填，您的 AccessKey Secret,
            access_key_secret=access_key_secret
        )
        # Endpoint 请参考 https://api.aliyun.com/product/Dysmsapi
        config.endpoint = f'dysmsapi.aliyuncs.com'
        self.sms_client = Dysmsapi20170525Client(config)

    def send_sms(self, phone_number, message_params, template_code, sign_name):
        """
        :param phone_number:
        :param message_params: {"name": "brotherbaby", "shoes": "123"}
        :param template_code:
        :param sign_name:
        :return:
        """
        send_sms_request = dysmsapi_20170525_models.SendSmsRequest(
            phone_numbers=phone_number,
            sign_name=sign_name,
            template_code=template_code,
            template_param=json.dumps(message_params)
        )
        runtime = util_models.RuntimeOptions()
        try:
            send_ret = self.sms_client.send_sms_with_options(send_sms_request, runtime)
            send_ret_body = send_ret.body
            if send_ret_body.code != "OK":
                logger.error("send sms by alicloud failed with error: %s", send_ret_body.message)
                return False, send_ret_body.message
            logger.info("send sms by alicloud succ, phone: %s, message: %s", phone_number, message_params)
            return True, send_ret_body.message
        except Exception as error:
            logger.error(traceback.format_exc())
            UtilClient.assert_as_string(error.message)
